package DAO;

import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import Model.ISerializable;
import Model.Project;
import Model.Task;
import Model.XML_NAMES;
//import android.content.Context;

public class XML_DAO {

    // ////////////////////////////WRITER XML ////////////////////////////////
    final static String DATE_FORMAT = "dd/MM/yyyy";
   // public static Context context = null;

    public static String fromDateToString(Date d) {
        String correctFormat = null;
        try {
            if (d != null) {
                SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
                correctFormat = sdf.format(d);
            }
        } catch (Exception e) {
        }
        return correctFormat;
    }

    public static Date fromStringToDate(String d) {
        Date date = null;
        try {
            if (d == null || d.equals("")) {
                return date;
            }
            if (d != null && !d.equals(" ")) {
                SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT);
                date = sdf.parse(d);
            }
        } catch (Exception e) {
        }
        return date;

    }

    private static String toXML(ISerializable instance) {
        StringBuilder sb = new StringBuilder();

        sb.append("<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>");
        sb.append(serialize(instance));

        return sb.toString();
    }

    private static String serialize(ISerializable instance) {
        StringBuilder sb = new StringBuilder();
        Class instanceClass = instance.getClass();

        try {
            // The opening xml tag of the instance
            sb.append("<");
            sb.append(instanceClass.getSimpleName());
            sb.append(">");
            //sb.append("\n");

            Field[] fields = instanceClass.getFields();

            for (Field f : fields) {
                String fieldName = f.getName();
                Object fieldValue = f.get((instance));

                // THE OPEN XML TAG OF EACH FIELD
                sb.append("<");
                sb.append(fieldName);
                sb.append(">");

                if (fieldValue instanceof Collection) {
                    Collection collection = (Collection) fieldValue;
                    Object[] array = collection.toArray();

                    for (int i = 0; i < array.length; i++) {
                        if (array[i] instanceof ISerializable) {
                            sb.append(serialize((ISerializable) array[i]));
                        }
                    }
                } else {
                    sb.append((fieldValue instanceof Date) ? fromDateToString((Date) fieldValue) : fieldValue.toString());
                }

                // THE CLOSE XML TAG OF EACH FIELD
                sb.append("</");
                sb.append(fieldName);
                sb.append(">");

            }

            // The closing xml tag of the instance
            sb.append("</");
            sb.append(instanceClass.getSimpleName());
            sb.append(">");
        } catch (Exception e) {
        } finally {
            return sb.toString();
        }
    }

    public static void writeProject(Project project) {
        try {
            String projectXML = toXML(project);
            String fileName = project.projectName;
            FileOutputStream outputStream = null;
           // outputStream = context.openFileOutput(fileName + ".xml", Context.MODE_PRIVATE);
            outputStream.write(projectXML.getBytes());
            outputStream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // //////////////////////////////READ XML ////////////////////////////////
    private static void readProjectBasic(Project project, Element root) {
        String nameElement = root.getElementsByTagName(XML_NAMES.PROJECT_NAME).item(0)
                .getTextContent();
        String descriptionElement = root
                .getElementsByTagName(XML_NAMES.PROJECT_DESCRIPTION).item(0)
                .getTextContent();
        String startDateElement = root.getElementsByTagName(XML_NAMES.PROJECT_START_DATE)
                .item(0).getTextContent();
        String finishDateElement = root
                .getElementsByTagName(XML_NAMES.PROJECT_FINISH_DATE).item(0)
                .getTextContent();

        project.projectName = nameElement;
        project.projectDescription = descriptionElement;
        project.projectStartDate = fromStringToDate(startDateElement);
        project.projectFinishDate = fromStringToDate(finishDateElement);
    }

    private static void readTaskList(Project project, Element root) {
        Element taskListElement = (Element) root.getElementsByTagName(
                XML_NAMES.PROJECT_TASK_LIST).item(0);
        NodeList listOfTasks = taskListElement.getElementsByTagName(XML_NAMES.TASK);
        int taskListLength = listOfTasks.getLength();

        for (int i = 0; i < taskListLength; i++) {
            Task task = new Task();
            Element taskElement = (Element) listOfTasks.item(i);

            String taskName = taskElement.getElementsByTagName(XML_NAMES.TASK_NAME).item(0).getTextContent();

            String taskDescription = taskElement.getElementsByTagName(XML_NAMES.TASK_DESCRIPTION).item(0).getTextContent();
            String taskStarDate = taskElement.getElementsByTagName(XML_NAMES.TASK_START_DATE).item(0).getTextContent();
            String taskFinishDate = taskElement.getElementsByTagName(XML_NAMES.TASK_FINISH_DATE).item(0).getTextContent();
            String percentage = taskElement.getElementsByTagName(XML_NAMES.TASK_PERCENTAGE).item(0).getTextContent();

            task.taskName = taskName;
            task.taskDescription = taskDescription;
            task.taskStartDate = fromStringToDate(taskStarDate);
            task.taskFinishDate = fromStringToDate(taskFinishDate);
            task.taskPorcent = Integer.parseInt(percentage);

            project.projectTaskList.add(task);

        }
    }
    /*
     private static void readSubTaskList(Task task, Element taskElement) {
     Element subTaskList = (Element) taskElement.getElementsByTagName(
     XML_NAMES.TASK_SUB_TASKS_LIST).item(0);

     if (subTaskList == null) {
     return;
     }

     NodeList listOfSubTasks = subTaskList.getElementsByTagName(XML_NAMES.TASK);
     int length = listOfSubTasks.getLength();

     for (int i = 0; i < length; i++) {
     Task subtask = new Task();

     Element subtaskElement = (Element) listOfSubTasks.item(i);

     String subtaskName = subtaskElement.getElementsByTagName(XML_NAMES.TASK_NAME)
     .item(0).getTextContent();

     if (!cachedTasks.contains(subtaskName)) {
     cachedTasks.add(subtaskName);

     String subtaskDescription = subtaskElement
     .getElementsByTagName(XML_NAMES.TASK_DESCRIPTION).item(0)
     .getTextContent();
     String subtaskStarDate = subtaskElement
     .getElementsByTagName(XML_NAMES.TASK_START_DATE).item(0)
     .getTextContent();
     String subtaskFinishDate = subtaskElement
     .getElementsByTagName(XML_NAMES.TASK_FINISH_DATE).item(0)
     .getTextContent();

     subtask.taskName = subtaskName;
     subtask.taskDescription = subtaskDescription;
     subtask.taskStartDate = fromStringToDate(subtaskStarDate);
     subtask.taskFinishDate = fromStringToDate(subtaskFinishDate);

     readSubTaskList(subtask, subtaskElement);

     task.taskSubTaskList.add(subtask);
     }
     }

     }
     */

    private static Project read(String fileName) {
        File f = null;
//        f = new File(context.getApplicationContext().getFilesDir() + "/" + fileName);
        String path = f.getAbsolutePath();

        Project project = new Project();
        try {
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            Document doc = docBuilder.parse(new File(path));

            Element root = (Element) doc.getDocumentElement();
            readProjectBasic(project, root);
            readTaskList(project, root);

        } catch (Exception e) {
            e.printStackTrace();
        }

        //System.out.println("se lee el proyecto: " + toXML(project));
        return project;
    }

    public static ArrayList<Project> readProjects() {
        ArrayList<Project> projects = new ArrayList<Project>();
        File[] files = null;
//        files = context.getApplicationContext().getFilesDir().listFiles();

        for (File file : files) {
            projects.add(read(file.getName()));
        }

        return projects;
    }

    public static void updateProjectWithName(String projectName, String newName, String description, String startDate, String finishDate) {
        try {
            File[] files = null;
//            files = context.getApplicationContext().getFilesDir().listFiles();

            projectName = projectName.concat(".xml");

            for (File file : files) {
                String name = file.getName();

                if (name.equals(projectName)) {
                    Project project = read(name);

                    if (file.delete()) {
                        project.projectName = newName;
                        project.projectDescription = description;
                        project.projectStartDate = fromStringToDate(startDate);
                        project.projectFinishDate = fromStringToDate(finishDate);
                        writeProject(project);
                    }
                    break;
                }
            }
        } catch (Exception e) {
        }
    }

    public static void deleteProjectWithName(String projectName) {
        try {
            File[] files = null;
//            files = context.getApplicationContext().getFilesDir().listFiles();

            projectName = projectName.concat(".xml");

            for (File file : files) {
                String name = file.getName();

                if (name.equals(projectName)) {
                    file.delete();
                    break;
                }
            }
        } catch (Exception e) {
        }
    }
}
